package yams.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import javafx.util.Callback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;
import yams.callback.IdCallback;
import yams.common.IRepository;
import yams.common.constants.*;
import yams.common.exception.BreezeeException;
import yams.domain.*;
import yams.repository.IBillRepository;
import yams.repository.IContractRepository;
import yams.repository.IHouseRepository;
import yams.repository.IUserRepository;
import yams.service.*;
import yams.utils.SystemTool;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;

/**
 * 合同服务实现
 * Created by Silence on 2017/5/3.
 */
@Service("contractService")
public class DefaultContractService implements IContractService {

    @Resource
    private IWeChatService weChatService;
    @Resource
    private IHouseService houseService;
    @Resource
    private IBillService billService;

    @Autowired
    private IUserRepository userRepository;
    @Autowired
    private IContractRepository contractRepository;
    @Autowired
    private IHouseRepository houseRepository;
    @Autowired
    private IBillRepository billRepository;
    @Autowired
    private IdCallback idCallback;

    private final JdbcTemplate jdbcTemplate;
    private final PlatformTransactionManager transactionManager;

    public DefaultContractService(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {
        this.jdbcTemplate = jdbcTemplate;
        this.transactionManager = transactionManager;
    }

    @Override
    public IRepository<ContractEntity> getRepository() {
        return contractRepository;
    }

    @Override
    public ContractEntity saveInfo(ContractEntity contractEntity, Callback<ContractEntity, Object>[] callback) throws BreezeeException {
        HouseEntity houseEntity = houseRepository.findOne(contractEntity.getHouse().getId());
        boolean billing = (contractEntity.getId() == null && contractEntity.getGenerateBill());
        contractEntity = contractRepository.saveEntity(contractEntity, callback);
        if (billing)
            billService.generateBill(contractEntity);
        Integer  status=  contractEntity.getStatus();
        switch (status){
            case 0: houseEntity.setStatus(HouseStatusEnum.CHECKED.getValue()); break;
            case 1: houseEntity.setStatus(HouseStatusEnum.CHECKED.getValue()); break;
            case 2: houseEntity.setStatus(HouseStatusEnum.EMPTY.getValue()); break;
            case 3: houseEntity.setStatus(HouseStatusEnum.CHECKED.getValue()); break;
            case 4: houseEntity.setStatus(HouseStatusEnum.CHECKED.getValue()); break;

        }
       // houseEntity.setStatus(HouseStatusEnum.CHECKED.getValue());
        houseRepository.saveEntity(houseEntity);
        return contractEntity;
    }

    /**
     * 生成房租账单
     * @param resultList
     */
    @Override
    public void generateRentBill(List<String> resultList){

        for(String id : resultList){
            ContractEntity contract = contractRepository.getOne(id);

            BillEntity billEntityCondition = new BillEntity();
            billEntityCondition.getProperties().put("status", BillStatusEnum.UNPAID.getValue());
            billEntityCondition.getProperties().put("type", BillTypeEnum.CONTRACT.getValue());
            billEntityCondition.getProperties().put("contract_id_obj_ae",id);
            Long currentUnpaidBillCnt = billService.count(billEntityCondition);
            //如果执行中的合同下面还存在未支付的账单，则直接跳过，避免重复生成账单
            if(currentUnpaidBillCnt != null && currentUnpaidBillCnt > 0){
                continue;
            }

            HouseEntity house = houseRepository.findByCode(contract.getHouse().getCode());
            UserEntity manager = userRepository.findOne(house.getManager());
            UserEntity user = contract.getUser();

            BigDecimal total = new BigDecimal(0);
            BillEntity billEntity = new BillEntity();
            billEntity.setStatus(0);
            billEntity.setType(1);
            billEntity.setContract(contract);
            billEntity.setUser(user);
            billEntity.setHouse(house);
            if (billEntity.getRentalAmount() == null){
                Integer cycle = contract.getPayCycle();
                BigDecimal rentalAmount = new BigDecimal(contract.getRental()).setScale(2,BigDecimal.ROUND_HALF_UP);
                switch (cycle){
                    case 2:
                        rentalAmount = rentalAmount.multiply(new BigDecimal(2));
                        break;
                    case 3:
                        rentalAmount = rentalAmount.multiply(new BigDecimal(3));
                        break;
                    case 6:
                        rentalAmount = rentalAmount.multiply(new BigDecimal(6));
                        break;
                    case 12:
                        rentalAmount = rentalAmount.multiply(new BigDecimal(12));
                        break;
                    default:
                        break;
                }
                billEntity.setRentalAmount(rentalAmount);
            }
            total = total.add(billEntity.getRentalAmount());
            //加物业费
//            total=total.add(BigDecimal.valueOf((billEntity.getHouse().getPropertyFee())
//                    *(billEntity.getHouse().getArea())));
            //默认不更新合同，但如果是首次支付，支付金额需要加入押金，并且需要更新押金状态
            boolean updateContract = false;
            if (contract.getPayStatus() == null || contract.getPayStatus() != 1) {
                billEntity.setPledgeAmount(new BigDecimal(contract.getPledge()).setScale(2,BigDecimal.ROUND_HALF_UP));
                total = total.add(billEntity.getPledgeAmount());
                contract.setPayStatus(1);
                updateContract = true;
            }
            billEntity.setTotalAmount(total);
            LocalDate ld = LocalDate.now();
            billEntity.setCode("1" + contract.getCode() + "-" + ld.toString().replace("-", ""));
            billEntity.setName(contract.getHouseName() + ld.toString() + "合同账单");
            if (billEntity.getDiscount() != null) {
                billEntity.setActualAmount(billEntity.getTotalAmount().multiply(billEntity.getDiscount()));
            } else {
                billEntity.setActualAmount(billEntity.getTotalAmount());
            }
            billService.getRepository().saveEntity(billEntity, new Callback[]{idCallback});
            //更新押金状态（1押金已入账单 0押金未入账单）
            if (updateContract){
                contractRepository.saveEntity(contract);
            }

            //给客户发送账单消息
            WechatTemplateMsg templateMsg = new WechatTemplateMsg();
            templateMsg.setTouser(user.getWeChat());
            templateMsg.setTemplate_id("8TBpNPfFKp8OEOVQqXHsPEcXHUvQuGjTZa9HKQuePqM");
            templateMsg.setUrl("http://"+ Constants.WECHAT_URL+"/yams/view/account?openId="+user.getWeChat());
            TreeMap<String,TreeMap<String,String>> map = Maps.newTreeMap();
//          酒店名称：{{keyword1.DATA}}
//          入住时间：{{keyword2.DATA}}
//          退房时间：{{keyword3.DATA}}
//          订单金额：{{keyword4.DATA}}
//          订单类型：{{keyword5.DATA}}
            map.put("first", templateMsg.item("尊敬的客户，您好！您的新账单已出，请在12小时内完成支付","#173177"));
            map.put("keyword1", templateMsg.item(house.getApartmentName()+"(房间号:"+house.getHouseNumber()+")",""));
            map.put("keyword2", templateMsg.item(SystemTool.dateToString(contract.getStartDate(),
                    "yyyy-MM-dd HH:mm:ss"),""));
            map.put("keyword3", templateMsg.item(SystemTool.dateToString(contract.getEndDate(),
                    "yyyy-MM-dd HH:mm:ss"),""));
            map.put("keyword4", templateMsg.item(total.toString()+"元",""));
            map.put("keyword5", templateMsg.item( updateContract? "房租,押金及物业费":"房租",""));
            map.put("remark", templateMsg.item("若有疑问请与管理员("+manager.getName()+","+manager.getPhone()+")联系","#173177"));
            templateMsg.setData(map);
            String jsonTempl = JSONObject.toJSONString(templateMsg);

            try {
                weChatService.sendTemplate(jsonTempl);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 合同到期 更改合同和房屋状态
     * @param resultList
     */
    @Override
    public void finishContracts(List<String> resultList){
        for(String id : resultList){
            ContractEntity contract = contractRepository.getOne(id);
            contract.setStatus(ContractStatusEnum.FINISHED.getValue());
            String houseId = contract.getHouse().getId();
            HouseEntity house = houseRepository.getOne(houseId);
            house.setStatus(HouseStatusEnum.EMPTY.getValue());

            contractRepository.saveEntity(contract);
            houseRepository.saveEntity(house);
        }
    }

    /**
     * 生成合同编码
     * @param contractEntity
     * @return
     */
    @Override
    public ContractEntity gaenerateContractCode(ContractEntity contractEntity) {

        String date = LocalDate.now().toString();
        String sql="select max(code) from t_contract";
        TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);
        return transactionTemplate.execute(status ->{
            String maxCode = jdbcTemplate.queryForObject(sql,String.class);
            String beforeNumberChar;
            String maxCodeDate=maxCode.substring(2,10);
            String nowDate=date.replace("-", "");
            if(maxCodeDate.equals(nowDate)){
                String lastChar=maxCode.substring(0,11);
                Integer max = 1;
                if(!StringUtils.isEmpty(maxCode)){
                    max = (Integer.valueOf(maxCode.substring(11))+1);
                }
                String len = max.toString();
                String sum = null;
                switch (len.length()){
                    case 1:
                        sum="000"+max;
                        break;
                    case 2:
                        sum="00"+max;
                        break;
                    case 3:
                        sum="0"+max;
                        break;
                    case 4:
                        sum=""+max;
                        break;

                }
                beforeNumberChar=lastChar+sum;
            }else{
                beforeNumberChar="CC"+nowDate+"-0001";
            }
            contractEntity.setCode(beforeNumberChar);
            return contractEntity;
        });
    }

    /**
     * 查找即将到期合同，并给客户发送微信消息
     */
    @Override
    public void checkoutHouse(){
        ContractEntity contractCondition1 = new ContractEntity();
        contractCondition1.getProperties().put("status", ContractStatusEnum.EXECUTING.getValue());
        contractCondition1.getProperties().put("endDate_gt", Date.from(LocalDateTime.now()
                .atZone(ZoneId.systemDefault()).toInstant()));
        contractCondition1.getProperties().put("endDate_le", Date.from(LocalDateTime.now().plusDays(5)
                .atZone(ZoneId.systemDefault()).toInstant()));
        List<ContractEntity> list = listAll(contractCondition1);

        for(ContractEntity contract : list){
            HouseEntity house = houseRepository.findByCode(contract.getHouse().getCode());
            UserEntity manager = userRepository.findOne(house.getManager());
            UserEntity user = contract.getUser();
            //给客户发送消息
            WechatTemplateMsg templateMsg = new WechatTemplateMsg();
            templateMsg.setTouser(user.getWeChat());
            templateMsg.setTemplate_id("EOsO28yslxmcofRYgbWndtOP_4Ze67hLm-tir_4TiY0");
            templateMsg.setUrl("http://"+Constants.WECHAT_URL+"/yams/view/account?openId="+user.getWeChat());
            TreeMap<String,TreeMap<String,String>> map = Maps.newTreeMap();
//            门店：{{keyword1.DATA}}
//            房型：{{keyword2.DATA}}
//            退房时间：{{keyword3.DATA}}
            map.put("first", templateMsg.item("尊敬的客户，您好！您的合同即将到期","#173177"));
            map.put("keyword1", templateMsg.item(house.getApartmentName(),"#173177"));
            map.put("keyword2", templateMsg.item(house.getHouseNumber(),"#173177"));
            map.put("keyword3", templateMsg.item(SystemTool.dateToString(contract.getEndDate(),
                    "yyyy-MM-dd HH:mm:ss"),"#173177"));
            map.put("remark", templateMsg.item("如果您要续住，请与管理员("+manager.getName()+","+manager.getPhone()+")联系","#173177"));
            templateMsg.setData(map);
            String jsonTempl = JSONObject.toJSONString(templateMsg);

            try {
                weChatService.sendTemplate(jsonTempl);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}
